package notes.java.concurrent;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 测试原子性
 * 修改T1_TestCountDownLatch.java(线程不安全，每次返回结果不一致)
 * 把原来的计算Int类型改为AtomicInteger（线程安全，每次返回结果一致）
 * @author wangcs
 */
public class T3_TestAtomic {

	// 现在要模拟一个并发程序，有5000个请求，并发量是200，对一个数值做加法计算，所有线程处理完后，打印出结果数

	// 请求数
	private static int clientReqNum = 5000;
	// 并发数
	private static int threadSize = 200;
	// 计数从0开始
	private static /*int*/ AtomicInteger count = /*0*/ new AtomicInteger(0);

	// 加法
	private static void add() {
		/*count++;*/ 
		count.incrementAndGet();
	}

	public static void main(String[] args) throws Exception {
		// 创建一个线程池
		ExecutorService excutorService = Executors.newCachedThreadPool();

		// 定义一个5000大小的计数器
		CountDownLatch countDownLatch = new CountDownLatch(clientReqNum);
		// 定义一个并发200的信号量
		Semaphore semaphore = new Semaphore(threadSize);

		// 启5000个线程
		for (int i = 0; i < clientReqNum; i++) {
			excutorService.execute(() -> {
				try {
					semaphore.acquire(); // 是否在200个并发量内，是就可以执行，不是就抛弃
					add(); // 加法处理
					semaphore.release();// 释放
					countDownLatch.countDown(); // 每运行一个线程后减1
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			});
		}

		// 等待所有线程运行完
		countDownLatch.await();
		// 关闭线程池
		excutorService.shutdown();
		// 打印结果
		System.out.println("count:" + count.get());
	}
}
